講完 Image 跟 Container 的使用,接著就要來講一下 Docker 中比較有趣的東西了,前面都是直接上 Docker Hub 抓下來的,但是如果需求比較特殊, Docker Hub 上面並沒有 Image 時又該怎麼辦呢?
因此這篇就是怎麼生出一個 Image ,不過再生出來之前需要先準備一下。
首先先建立如下的架構。
test-project
├── app.py
├── Dockerfile
└── requirements.txt
接著是每個檔案的內容。
app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello World!"
if __name__ == "__main__":
app.run()
requirements.txt
click==8.1.2
colorama==0.4.4
Flask==2.1.1
gunicorn==20.1.0
importlib-metadata==4.11.3
itsdangerous==2.1.2
Jinja2==3.1.1
MarkupSafe==2.1.1
Werkzeug==2.1.1
zipp==3.8.0
Dockerfile
FROM python:3.9.10-alpine3.15
WORKDIR /test-project
COPY * .
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
接著我們先下個指令將 Image 建立出來。
$ docker build --no-cache -t my-project .
等他跑完後,然後查看一下所有的 Image ,看看有沒有多出一個新的 Image 。
$ docker images
正常應該會出現 my-project
的 Image ,我們先把它啟動起來看看。
$ docker run -it --rm -p 5000:5000 my-project
然後就可以到 http://localhost:5000 看到剛剛啟動的服務了。
那麼接著就來說一下剛剛 Dockerfile 做了什麼事吧。
首先第一行 FROM python:3.9.10-alpine3.15
就是宣告說要使用的基底 Image ,可以當成是開發環境的意思,基本上都會放在最上面,且通常只會有一行(我會這麼說的意思是可以很多個 FROM
,但我沒怎麼見過超過一個 FROM
的 Dockerfile)。
而上面這行的意思是使用 alpine3.15 的作業系統,並且包含 python:3.9.10 的環境,而這個 Image 放在 python
的分類底下。
如果你是用 Node.js 或其他開發環境的話,也都可以到 DockerHub 上面對應的分類底下去尋找符合需求的 Image 。
接著是第二行 WORKDIR /test-project
就是指定工作的目錄,如果不指定的話預設是在根目錄底下 /
,如果沒有會自動建立。我習慣會建立一個工作目錄,專門放專案有關的東西,不然放在根目錄總覺得哪裡怪怪的。
第三行就簡單了 COPY * .
就是把目前目錄底下的東西全部複製進去而已。
第四行也很簡單 RUN pip install -r requirements.txt
就只是安裝好所有需要的套件而已。
第五行雖然簡單但是需要注意 EXPOSE 5000
就是宣告可以開放的 PORT ,但是這邊只是宣告有哪個 PORT 可以接而已,並不會自動接上,所以需要再 run 的時候把它接出來。
第六行 CMD ["python", "app.py"]
就是執行起來的指令啦。
看到這邊不知道各位有沒有發現,第四行跟第六行似乎作用相同,為什麼一個是 RUN
另一個是 CMD
呢?
這是因為 RUN
是在建立 Image 時就會執行的指令, CMD
則是啟動時才會執行的指令。因此大多都會使用 RUN
來安裝及設定相關的東西,真正需要執行時則會使用 CMD
。
那麼就先到這邊,恭喜各位已經會了最基本的 Dockerfile 了。
大家掰~掰~